from typing import Annotated

from aiogram import Bot
from dishka import FromDishka
from dishka.integrations.fastapi import inject
from fastapi import APIRouter

from weed_shop.api.controllers.requests.cart import WebAppCart
from weed_shop.core.config import TgBotConfig
from weed_shop.core.converters.product import convert_products_to_products_with_quantity
from weed_shop.core.models.dto import OrderDTO
from weed_shop.core.models.dto.cart import CartLineDTO
from weed_shop.core.models.enums.currency import Currency
from weed_shop.core.models.enums.order import DeliveryMethod, OrderStatus
from weed_shop.core.models.enums.user import UserRole
from weed_shop.core.price_calculation import calculate_total_summ
from weed_shop.infrastructure.database.converters.order import convert_cart_lines_to_order_line
from weed_shop.infrastructure.database.services import (
    BotSettingsService,
    DiscountService,
    OrderService,
    PaymentMethodService,
    ProductService,
    ShopService,
    StatsService,
    UserService,
)
from weed_shop.tg_bot.keyboards.inline import order_shipping_kb
from weed_shop.tg_bot.services.locale import Localizator
from weed_shop.tg_bot.services.tg_helpers import broadcast, send_tg_message

order_router = APIRouter(prefix="/order", tags=["order"])


@order_router.post("/create", description="Создаем заказ из ресторана")
@inject
async def create_order(
    cart: WebAppCart,
    user_tg_id: int,
    user_service: Annotated[UserService, FromDishka()],
    product_service: Annotated[ProductService, FromDishka()],
    order_service: Annotated[OrderService, FromDishka()],
    bot_settings_service: Annotated[BotSettingsService, FromDishka()],
    discount_service: Annotated[DiscountService, FromDishka()],
    shop_service: Annotated[ShopService, FromDishka()],
    payment_method_service: Annotated[PaymentMethodService, FromDishka()],
    stats_service: Annotated[StatsService, FromDishka()],
    bot: Annotated[Bot, FromDishka()],
    localizator: Annotated[Localizator, FromDishka()],
    tg_config: Annotated[TgBotConfig, FromDishka()],
) -> OrderDTO:
    """Создаем заказ из ресторана"""

    cart_lines = [
        CartLineDTO(
            title=item.title,
            product_id=item.id,
            quantity=item.quantity,
            final_unit_price=item.discounted_price,
        )
        for item in cart.items
    ]
    user = await user_service.get_user_by_telegram_id(user_tg_id)
    shop = await shop_service.get_shop_by_delivery_zone_id(user.delivery_zone_id)
    bot_settings = await bot_settings_service.get_bot_settings()
    discounts = await discount_service.get_discounts_for_shop(shop.id)
    payment_method = await payment_method_service.get_payment_method_by_currency(Currency.thb)

    products = [await product_service.get_product_by_id(line.product_id) for line in cart_lines]
    products_with_quantity = convert_products_to_products_with_quantity(cart_lines, products)
    order_summ = calculate_total_summ(
        products_with_quantity,
        bot_settings.maximum_bonus_discount_percent,
        discounts,
    )
    order = await order_service.create_order(
        summ=float(order_summ),
        original_summ=float(order_summ),
        user_id=user.id,
        shop_id=shop.id,
        delivery_zone_id=user.delivery_zone_id,
        payment_method_id=payment_method.id,
        order_lines=convert_cart_lines_to_order_line(cart_lines),
        comment=user.username,
        delivery_method=DeliveryMethod.restaurant,
        order_status=OrderStatus.payment_confirmed,
    )
    for line in order.order_lines:
        await product_service.increase_product_sold_count(line.product_id, line.quantity)
    await stats_service.add_stats(products_purchased=len(order.order_lines))
    await stats_service.add_stats(orders_created=1)

    locale = localizator.get_by_locale("en")
    await send_tg_message(
        bot,
        tg_config.admin_channel_id,
        locale.get(
            "new-order-msg",
            order_id=order.id,
            shop_id=shop.id,
            order_summ=order.summ,
            currency_symbol=payment_method.currency_symbol.value,
        ),
    )

    stuff = await user_service.get_users_by_role_and_shop_id(UserRole.stuff, shop.id)
    delivery_type = "DELIVERY"
    if order.delivery_method == DeliveryMethod.self_pickup:
        delivery_type = "PICKUP BY CUSTOMER"
    elif order.delivery_method == DeliveryMethod.restaurant:
        delivery_type = "RESTAURANT"

    await broadcast(
        bot,
        stuff,
        locale.get("new-order-for-shipping-msg", delivery_type=delivery_type, order_id=order.id),
        reply_markup=order_shipping_kb(locale, order.id),
    )

    return order
